#include "MainApplication.h"
#include "CameraManager.h"

#include <OgreMeshManager.h>
#include <OgreMaterialManager.h>
#include <OgreEntity.h>

#include "../editor/Model/Geometry.h"
#include "../editor/FileIO/FileIO.h"
#include "../editor/OgreLoader/IndexedMesh.h"

using namespace Viewer;

//-------------------------------------------------------------------------------------
MainApplication::MainApplication(void)
:moveManager(0)
{
}
//-------------------------------------------------------------------------------------
MainApplication::~MainApplication(void)
{
}

//-------------------------------------------------------------------------------------
void MainApplication::createScene(void)
{
   
   // lumière ambiante (ici noire car utilise uniquement les lumière "point"
    mSceneMgr->setAmbientLight(Ogre::ColourValue(0, 0, 0));
    mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_MODULATIVE_INTEGRATED);
 
    //Creation de l'entité "ninja"
    entNinja = mSceneMgr->createEntity("Ninja", "ninja.mesh");
    entNinja->setCastShadows(true);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(entNinja);
    mCameraMan->attach(entNinja);
    moveManager = new MoveManager(entNinja->getParentNode(), mKeyboard, 0);
 
    // Set idle animation
    /*mAnimationState = entNinja->getAnimationState("Idle");
    mAnimationState->setLoop(true);
    mAnimationState->setEnabled(true);*/
    
    
    loadMap();
 
    //textures
    
 
    //Creation de la lumière "point"
    Ogre::Light* pointLight = mSceneMgr->createLight("pointLight");
    pointLight->setType(Ogre::Light::LT_POINT);
    pointLight->setPosition(Ogre::Vector3(0, 150, 250));
 
    pointLight->setDiffuseColour(1.0, 1.0, 1.0);
    pointLight->setSpecularColour(1.0, 1.0, 1.0); 
}

//-------------------------------------------------------------------------------------

bool MainApplication::frameRenderingQueued(const Ogre::FrameEvent& evt)
{
  
    //mAnimationState->addTime(evt.timeSinceLastFrame);//animation du mesh
    bool result = BaseApplication::frameRenderingQueued(evt);
    if(moveManager)
        moveManager->nextFrame(evt);
    if(mCameraMan)
        mCameraMan->nextFrame(evt);
    return result;
}

bool MainApplication::keyPressed(const OIS::KeyEvent& arg)
{
    BaseApplication::keyPressed(arg);
    return moveManager->keyPressed(arg);
}

bool MainApplication::keyReleased(const OIS::KeyEvent& arg)
{
    return moveManager->keyReleased(arg);
}

void MainApplication::createCamera(void)
{
  
    // creation de la camera
    mCamera = mSceneMgr->createCamera("PlayerCam");
    
    // régler la position, direction de la caméra  
    mCamera->setPosition(Ogre::Vector3(0,300,500));
    mCamera->lookAt(Ogre::Vector3(0,200,0));
    
    // règle la distance de coupure
    mCamera->setNearClipDistance(5);
    
    // create a default camera controller
    mCameraMan = new CameraManager(mCamera);   
}
//-------------------------------------------------------------------------------------
void MainApplication::createViewports(void)
{
    // Create one viewport, entire window
    //Ici, on crée un seul viewport qui vsionne toute la scène car on n'utilise qu'une seule camera
    Ogre::Viewport* vp = mWindow->addViewport(mCamera);
    vp->setBackgroundColour(Ogre::ColourValue(0,0,0));
    // Alter the camera aspect ratio to match the viewport
    mCamera->setAspectRatio(Ogre::Real(vp->getActualWidth()) / Ogre::Real(vp->getActualHeight()));  
    
}
 
void MainApplication::loadMap()
{
    Model::BuildingMap buildingMap;

    FileIO::loadBuildingMap(buildingMap, "clubs.woe");

    IndexedMesh generator(buildingMap.walls(), 7.0);
    generator.setCeilMaterial("General/Ceiling");
    generator.setFloorMaterial("General/Floor");
    generator.setWallMaterial("General/CrispyWall");
    
    Ogre::ManualObject* walls = generator.get(mSceneMgr, 250, "Walls");
    walls->setCastShadows(true);
    
    Ogre::SceneNode* building = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    building->attachObject(walls);
    
   
}

int main(int argc, char *argv[])
{
    MainApplication app;

    try {
        app.go();
    } catch( Ogre::Exception& e ) {
        std::cerr << "An exception has occured: " <<
            e.what() << std::endl;
    }

    return 0;
}

